﻿/*
 * Test classes for SSAS Partition Manager 
 * https://ssaspartitionmanager.codeplex.com/
 * 
 * Written by Dr. John Tunnicliffe of Decision Analytics, May 2015
 * eMail: john@decision-analytics.co.uk 
 * http://www.decision-analytics.co.uk/
 * https://www.linkedin.com/in/drjohntunnicliffe
 * 
 * Tests written with FluentAssertions, XUnit and Moq which can be installed from Nuget.  
 * 
 * FluentAssertions
 * http://www.fluentassertions.com/ 
 * 
 * XUnit
 * http://xunit.github.io/
 * 
 * Moq
 * https://github.com/Moq/moq4
 */

namespace AmoExtensions.UnitTests
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Dynamic;
    using AmoExtensions;
    using FluentAssertions;
    using Xunit;
    using Moq;

    public class UnitTestPartition
    {
        #region Constructor Tests
        [Fact]
        public void Constructor_NullServerThrowsException()
        {
            Action action = () => new Partition(null);
            action
                .ShouldThrow<ArgumentNullException>();
        }

        [Fact]
        public void Constructor_DisconnectedServerThrowsException()
        {
            // setup
            var mock = new Mock<IAmoServer>();
            mock.SetupGet(x => x.Connected).Returns(false);
            IAmoServer server = mock.Object;

            // test
            Action action = () => new PartitionManager(server, null);
            action
                .ShouldThrow<ApplicationException>()
                .WithMessage(Partition.SsasServerNotConnected);
        }
        #endregion

        #region Exists
        [Fact]
        public void Exists_ThrowsDueToNullMeasureGroup()
        {
            // setup
            IPartition partition = MockObjects.GetMockedPartition();

            // test
            Action action = () => partition.Exists();
            action
                .ShouldThrow<ApplicationException>()
                .WithMessage("Error occurred while attempting to find measure group*");
        }
        #endregion

        #region CreatePartition
        [Fact]
        public void CreatePartition_ThrowsDueToNullMeasureGroup()
        {
            // setup
            IPartition partition = MockObjects.GetMockedPartition();

            // test
            Action action = () => partition.Create();
            action
                .ShouldThrow<ApplicationException>()
                .WithMessage("Error occurred while attempting to find measure group*");
        }
        #endregion

        #region HasValidWhereClause
        [Theory]
        [InlineData("select * from mytable where 1=0", true)]
        [InlineData("select * from mytable where 1 = 0", true)]
        [InlineData("select * from mytable WHERE 1 = 0", true)]
        [InlineData("select * from mytable WHERE     1 = 0", true)]
        [InlineData("select * from mytable where\t1\t=\t0", true)]  // contains tabs.  Note that the \t is replaced by a tab
        [InlineData("select 1 = 0", false)]  // no where
        [InlineData("select * from mytable where 0=0", false)] 
        [InlineData("select * from mytable where 0=1", false)]
        [InlineData("select * from mytable where 0 = 1", false)]
        [InlineData("select * from mytable   1 = 0", false)]  // no where
        [InlineData("select * from mytable WHERE test = 'Fred'", false)]
        [InlineData("select * from mytable", false)]
        [InlineData("", false)]
        public void HasValidWhereClause_Matches(string sql, bool matchExpected)
        {
            // setup
            IPartition partition = MockObjects.GetMockedPartition();

            // test
            partition.HasValidWhereClause(sql).Should().Be(matchExpected);
        }

        [Fact]
        public void HasValidWhereClause_NullParameterThrows()
        {
            // setup
            IPartition partition = MockObjects.GetMockedPartition();

            // test
            Action action = () => partition.HasValidWhereClause(null);
            action.ShouldThrow<ArgumentNullException>();
        }
        #endregion

        #region ProcessPartition
        [Fact]
        public void ProcessPartition_ThrowsDueToNullMeasureGroup()
        {
            // setup
            IPartition partition = MockObjects.GetMockedPartition();

            // test
            Action action = () => partition.Process();
            action
                .ShouldThrow<ApplicationException>()
                .WithMessage("Error occurred while attempting to find measure group*");
        }
        #endregion

        #region DeletePartition
        [Fact]
        public void DeletePartition_ThrowsDueToNullMeasureGroup()
        {
            // setup
            IPartition partition = MockObjects.GetMockedPartition();

            // test
            Action action = () => partition.Delete();
            action
                .ShouldThrow<ApplicationException>()
                .WithMessage("Error occurred while attempting to find measure group*");
        }
        #endregion

        #region FromDynamic
        [Fact]
        public void FromDynamic_ConnectedServerShouldNotThrow()
        {
            // setup

            // test
            Action action = () => Partition.FromDynamic(MockObjects.GetMockedConnectedServer(), MockObjects.GetMockedDynamic());
            action
                .ShouldNotThrow();
        }

        [Fact]
        public void FromDynamic_DisconnectedServerShouldThrow()
        {
            // setup

            // test
            Action action = () => Partition.FromDynamic(MockObjects.GetMockedDisconnectedServer(), MockObjects.GetMockedDynamic());
            action
                .ShouldThrow<ApplicationException>()
                .WithMessage(Partition.SsasServerNotConnected);
        }

        [Fact]
        public void FromDynamic_OddShapedDynamicShouldThrow()
        {
            // this dynamic has the wrong property names
            dynamic newDynamic = new ExpandoObject();
            newDynamic.DatabaseName = "Database1";
            newDynamic.CubeName = "Cube1";
            newDynamic.MeasureGroupName = "MeasureGroup1";

            Action action = () => Partition.FromDynamic(MockObjects.GetMockedConnectedServer(), newDynamic);
            action
                .ShouldThrow<ApplicationException>()
                .WithMessage("Failed to create partition from dynamic object*");
        }
        #endregion

    }
}

